<?php


namespace App\Http\Services;

use Lcobucci\Clock\FrozenClock;
use Lcobucci\JWT\Encoding\ChainedFormatter;
use Lcobucci\JWT\Encoding\JoseEncoder;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory;
use Lcobucci\JWT\Token\Builder;
use Lcobucci\JWT\Token\Parser;
use Lcobucci\JWT\Validation\Constraint\SignedWith;
use Lcobucci\JWT\Validation\Constraint\StrictValidAt;
use Lcobucci\JWT\Validation\Validator;
//一次请求中,只能是一个用户，使用单例
class jwtAuth
{
    static private $instance;

    private $token;         //生成的token

    private $parse;

    private $head; //存储jwt信息头,减少客户端字符串

    private $iss="http://api.xinzhu.com";

    private $aud="http://xinzhu.com";

    private $jti="w1efsqe1vfsfq";

    private $uid;

    private $key='MIICXAIBAAKBgQCFWK/aqPt2+6nj3ErH7YMuITUqi8tIvIo5dO69phLkgwEoQ5PAzoQgQggVMBNtcZJ4UJZ8hqEfqqyvLvR7AzSsHlsZZ7XQYuh9tnGG5eREk0wirvXWfl5SU+ARIldllY1tJL65I35JZnLZUZOlkSkcr7/VXowhxZk3A7Ybp74QvwIDAQABAoGAUOR9QcvTSNngtS81WlWWh8xzYU0O1CA0RijOj9QIkAF9GTztjEB73MnR93CDyJfmQAC7We2eHwS930Q/4cQPFh4J69fPUHP83BIJo8WA5MP7HnyLFQKShoDk6bn5nGZpJ5IcKGf0eC18L2kSSsObY1MhG1TR8mSDGw1c3dwsETkCQQDJoPkebx9ANxoeUMphsQXiNWCKTUVR8i93K313ud5RtUUZ+5AVmKkn4HStnhq3/hS87atjafdxNW8pZYFFvAQLAkEAqU37XbZ/w83X1x4AQUfUOmqtJ2KOtABC2vvDgoRMKQPy79rinA+Em6dE+KKtrZtCRU2jNfJSQxj3pbh9h2aCnQJBALeYDx7qOj+DrRGrqQyZX20iA10LjTJX32aYwC9znH80Gs7U5Nb1YhnAZR3uGBAvmHyLwYLNa5W2/Rhpp/Nyhw8CQAJMls9M/Ssxjm7Tb3lzekRY0oUoZ3u2TTIgHSWWmlosPY5YUJ+B7nEWsm8V9nnXE+1RAphm9AsJOcO8X6gJElkCQB8Ol4tXl8Wk0PJQ1KEqM+ZfFCWYV8YCHQMOJrHFf8dyMS1EdNlLhzrx8qyORavFZNUk/8Y5kcgyVmaeZdTofS0=';

    private $public_key='MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCFWK/aqPt2+6nj3ErH7YMuITUqi8tIvIo5dO69phLkgwEoQ5PAzoQgQggVMBNtcZJ4UJZ8hqEfqqyvLvR7AzSsHlsZZ7XQYuh9tnGG5eREk0wirvXWfl5SU+ARIldllY1tJL65I35JZnLZUZOlkSkcr7/VXowhxZk3A7Ybp74QvwIDAQAB';

    private $signer;


    /**
     * 私有化架构方法
     * jwtAuth constructor.
     */
    private function __construct()
    {
        $this->signer=new Sha256();
    }

    static public function getInstance()
    {
        if (!self::$instance instanceof self){
            self::$instance=new self();
        }
        return self::$instance;
    }

    private function __clone()
    {
        // TODO: Implement __clone() method.
    }

    /**
     * 获取token
     * @return mixed
     */
    public function getToken()
    {
        return $this->token;
    }

    /**
     * 生成token
     * @param $token
     * @return $this
     */
    public function setToken($token)
    {
        $this->token=(string)$token;
        return $this;
    }

    /**
     * 设置用户ID
     * @param $id
     * @return $this
     */
    public function setUid($id){
        $this->uid=$id;
        return $this;
    }

    /**
     * 获取用户ID
     * @param $id
     * @return $this
     */
    public function getUid(){
        return $this->uid;
    }


    /**
     * 数据加密
     * @param $data
     * @param $key
     * @return string
     */
    private function encrypt($data)
    {
        $char='';
        $str='';
        $key    =    md5($this->key);
        $x        =    0;
        $len    =    strlen($data);
        $l        =    strlen($this->key);
        for ($i = 0; $i < $len; $i++)
        {
            if ($x == $l)
            {
                $x = 0;
            }
            $char .= $key[$x];
            $x++;
        }
        for ($i = 0; $i < $len; $i++)
        {
            $str .= chr(ord($data[$i]) + (ord($char[$i])) % 256);
        }
        return base64_encode($str);
    }

    /**
     * 生成token字符串
     * @return $this
     */
    public function encode()
    {
        $time = time();
        $this->token = (new Builder())->issuedBy($this->iss)
        ->permittedFor($this->aud)
        ->identifiedBy($this->jti, true)//jwt识别码
        ->issuedAt($time)
        ->canOnlyBeUsedAfter($time) //生效时间
        ->expiresAt($time + 6048000) //有效期7天
        ->withClaim('uid', $this->uid)
        ->getToken($this->signer,new Key($this->key));

        return $this;
    }

    /**
     *解析令牌
     */
    public function decode($token)
    {
        $parser = new Parser(new JoseEncoder());
        try {
            $token = $parser->parse($token);
            $resData = $token->claims()->all();
            return $resData;
        } catch (\Exception $e) {
            return false;
        }
    }

    public function validateToken($_token)
    {
        //1、解析token
        $token=$this->decode($_token);

        //2、获取从token中解析出来的数据
        $aud = $token->getClaim('aud');
        $iss = $token->getClaim('iss');
        $jwt_id = $token->getHeader('jti');

        //3、使用当前时间进行验证
        $data = new ValidationData(); //使用当前时间进行验证

        //4、设置需要验证的数据
        $data->setIssuer($iss);
        $data->setAudience($aud);
        $data->setId($jwt_id);

        return $token->verify($this->signer, $this->key)&&$token->validate($data);

    }

}